package com.aop.aop;

import com.aop.annotation.Log;
import com.aop.domain.WebLog;
import com.aop.service.WebLogService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @Description:
 * @author: zxl
 * @Data:2021/3/24
 */
@Slf4j
@Aspect
@Component
public class WebLogAspect {
    @Resource
    private WebLogService webLogService;

    @Pointcut(("@annotation(com.aop.annotation.Log)"))
    public void webLog() {
    }

    @Around("webLog()")
    public Object around(ProceedingJoinPoint joinPoint) {
        //获取请求
        HttpServletRequest request = getRequest();
        Object result = null;
        try {
            log.info("开始");
            long startTime = System.currentTimeMillis();
            result = joinPoint.proceed();
            log.info("结束");
            long costTime = System.currentTimeMillis() - startTime;
            //获取注解
            Log log = getAnnotation(joinPoint);
            WebLog webLog = WebLog.builder().startTime(startTime).description(log.description()).httpMethod(request.getMethod()).ipAddress(request.getRemoteAddr()).uri(request.getRequestURI()).url(request.getRequestURL().toString()).timeCost(costTime).methodType(log.mediaType().name()).params(getParams(joinPoint).toString()).result(result.toString()).build();
            webLogService.save(webLog);
        } catch (Throwable throwable) {
            log.error(throwable.getMessage(), throwable);
        } finally {
            log.info("后置通知");
        }
        return result;
    }

    //获取请求
    private HttpServletRequest getRequest() {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        return attributes.getRequest();
    }

    //获取注解
    private Log getAnnotation(ProceedingJoinPoint joinPoint) {
        Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
        return method.getAnnotation(Log.class);
    }

    //获取参数
    private Object getParams(ProceedingJoinPoint joinPoint) {
        String[] paramNames = getSignature(joinPoint).getParameterNames();
        //参数值
        Object[] paramValues = joinPoint.getArgs();
        //存储参数
        Map<String, Object> params = new LinkedHashMap<>();
        for (int i = 0; i < paramNames.length; i++) {
            Object value = paramValues[i];
            if (value instanceof MultipartFile) {
                MultipartFile file = (MultipartFile) value;
                value = file.getOriginalFilename();
            }
            params.put(paramNames[i], value);
        }
        return params;
    }

    private MethodSignature getSignature(ProceedingJoinPoint joinPoint) {
        return (MethodSignature) joinPoint.getSignature();
    }
}
